package com.demarc.pesquisas.web.converter;

import java.util.Locale;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;

import com.demarc.pesquisas.infraestrutura.mensagem.MensagemJsfUtils;
import com.demarc.pesquisas.infraestrutura.web.jsf.JsfUtil;

public abstract class AbstractJodaTimeConverter implements Converter {

	private static final String JODA_TIME_MESSAGE_ID = "com.demarc.pesquisas.web.converter.AbstractJodaTimeConverter.JODATIME";

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Object getAsObject(FacesContext context, UIComponent component,
			String value) {
		Object object = null;

		if (!StringUtils.isBlank(value)) {
			Locale locale = context.getViewRoot().getLocale();
			try {
				object = getAsObject(parse(value.trim(), locale));
			} catch (Exception e) {
				FacesMessage facesMessage = MensagemJsfUtils.criarFacesMessage(
						FacesMessage.SEVERITY_ERROR, JODA_TIME_MESSAGE_ID,
						JsfUtil.getLabel(context, component));
				throw new ConverterException(facesMessage, e);
			}
		}
		return object;
	}

	public DateTime parse(String value, Locale locale) {
		// the formatter
		DateTimeFormatter formatter = new DateTimeFormatterBuilder()
				.appendPattern(getPattern()).toFormatter().withLocale(locale);
		// first, we parse to local date time
		LocalDateTime localDateTime = formatter.parseLocalDateTime(value);

		// gets the default time zone
		DateTimeZone zone = DateTimeZone.getDefault();
		// checks if the date is valid
		if (zone.isLocalDateTimeGap(localDateTime)) {
			// if not, it's summer time, so we add 1 hour.
			return localDateTime.plusHours(1).toDateTime();
		}

		// if the date is valid, parses the "old" way
		return formatter.parseDateTime(value);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getAsString(FacesContext context, UIComponent component,
			Object object) {
		String value = null;

		if (object != null) {
			value = getAsString(object);
		}
		return value;
	}

	protected abstract String getPattern();

	protected abstract String getAsString(Object object);

	protected abstract Object getAsObject(DateTime dateTime);
}